home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Other Stuff
/
Other Stuff ’97
/
PowerOS Development
/
booter
/
booter.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-26
|
4KB
|
149 lines
/*
boot.c
Application-Based Booter for PowerOS and OpenOS
copyright 1996-1997 by Ben Martz
all rights reserved world wide
ANY AND ALL MODIFICATIONS TO THIS SOURCE MUST CREDIT THE ORIGINAL
AUTHOR, BEN MARTZ (benmartz@ic.net), AND MUST BE GIVEN TO THE AUTHOR
FOR INTEGRATION INTO THE MAIN PowerOS SOURCE TREE. THANK YOU FOR YOUR
COOPERATION!
*/
#include <stdio.h>
#include "booter.h"
#include "boot.h"
#include "stdhdr.s"
#include "garymode.h"
#include <ShutDown.h>
KernelBootData *kvars;
DialogPtr status;
Ptr kernel;
long kernellen;
char *LogicalToPhysical(char *p, unsigned long plen);
void bootkernel(char *from, unsigned long len, KernelBootData *vars);
long elf_makeimage(char *fname, char **kptr);
void main(void) {
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(0L);
InitCursor();
status = GetNewDialog(128,nil,(WindowPtr) -1L); if(!status) return;
UpdateStatus("\pInitializing PowerOS Booter");
/* these will be passed into the kernel */
kvars = (KernelBootData *) NewPtrSysClear(sizeof(KernelBootData));
kvars->version = BOOTVERSION;
kvars->v_baseaddr = LMGetScrnBase();
kvars->v_rowbytes = (**(**LMGetMainDevice()).gdPMap).rowBytes & 0x3fff;
kvars->v_depth = (**(**LMGetMainDevice()).gdPMap).pixelSize;
kvars->v_width = (**LMGetMainDevice()).gdRect.right - (**LMGetMainDevice()).gdRect.left;
kvars->v_height = (**LMGetMainDevice()).gdRect.bottom - (**LMGetMainDevice()).gdRect.top;
Gestalt(gestaltPhysicalRAMSize, &(kvars->m_bytes));
UpdateStatus("\pLoading PowerOS Kernel");
if((kernellen = elf_makeimage("kernel.elf",&kernel)) < 0) {
UpdateStatus("\pFailed to load ELF binary! Click to exit...");
while(!Button());
ExitToShell();
}
/* we need to get the physical address of the kernel data */
LockMemory(kernel,kernellen);
/* translate the address */
kernel = LogicalToPhysical(kernel,kernellen);
if(kernel == ((char *)0xdeadbeef)) {
UpdateStatus("\pLogicalToPhysical failed! Click to exit...");
while(!Button());
ExitToShell();
}
/* this is a really good way to get a clean boot (from an application) */
UpdateStatus("\pShutting down MacOS");
ShutDwnInstall(NewShutDwnProc(boot), sdOnPowerOff);
ShutDwnPower();
/* just wait for the system to shutdown so our code stays in memory */
while(1) {
HideCursor();
SystemTask();
}
}
void UpdateStatus(unsigned char *string) {
short itemType;
Handle itemHandle;
Rect itemRect;
SetPort(status);
GetDialogItem(status,3,&itemType,&itemHandle,&itemRect);
DrawDialog(status);
EraseRect(&itemRect);
MoveTo(itemRect.left + (((itemRect.right - itemRect.left) / 2) - (StringWidth(string) / 2)),itemRect.bottom - 4);
DrawString(string);
}
void boot(void) {
UpdateStatus("\pBooting PowerOS");
EnterPriviledgedMode(bootkernel,(void *)kernel,(void *)kernellen,(void *)kvars);
/* ouch? */
UpdateStatus("\pIf you see this, your system is possessed!");
}
/* it appears that a 6100 running 7.6 is mapped 1:1 -- hmmm? */
char *LogicalToPhysical(char *p, unsigned long plen) {
LogicalToPhysicalTable table;
unsigned long count;
table.logical.address = p;
table.logical.count = plen;
count = sizeof(table) / sizeof(MemoryBlock) - 1;
if(GetPhysical(&table,&count) == noErr) {
return table.physical[0].address;
}
return (char *)0xdeadbeef;
}
asm void bootkernel(char *from, unsigned long len, KernelBootData *vars) {
/* turn off external interrupts during copy */
lis r9,MSR_KERNEL
ori r9,r9,MSR_KERNEL
mtmsr r9
/*
unlike some sloppy code that i've seen, a synchronizing
operation is only necessary AFTER the mtmsr -- read your
damn reference manuals!!!
*/
sync
/* relocate the kernel to zero */
mtctr r4
li r6,0
subi r3,r3,1
subi r6,r6,1
loop:
lbzu r9,1(r3)
stbu r9,1(r6)
bdnz+ loop
/* put the boot vars where they belong */
mr r3,r5
/* jump to zero */
lis r9,0
addi r9,r9,0
mtlr r9
blr
}